import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'dart:convert' as convert;

import 'package:flutter_blue/flutter_blue.dart';
import 'package:flutter_phoenix/flutter_phoenix.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hex/hex.dart';
import 'package:path_provider/path_provider.dart';
import 'package:realmega_ota/AppStateObserver.dart';
import 'package:realmega_ota/Global.dart';
import 'package:realmega_ota/realmega/ota_manager_ex.dart';
import 'package:realmega_ota/util/ble_manager.dart';
import 'package:realmega_ota/realmega/fcs_util.dart';
import 'package:realmega_ota/realmega/history_info.dart';
import 'package:realmega_ota/realmega/history_manager.dart';
import 'package:realmega_ota/realmega/running_log_manager.dart';
import 'package:realmega_ota/realmega/setting_and_filter_manager.dart';
import 'package:realmega_ota/util/ios_compat.dart';

import '../constants.dart';
import '../util/log_util.dart';
import '../util/util.dart';

class OtaManager{

  //是不是第二个版本的ota升级逻辑
  bool isV2Ota = false;

  bool inProgressing = false;
  // int progress = 0;

  // final StreamController<int> _progressController = StreamController.broadcast();
  // Stream<int> get progress => _progressController.stream.asBroadcastStream();
  // StreamSink<int> get _progressSink => _progressController.sink;
  //
  // final StreamController<bool> _inUpdateController = StreamController.broadcast();
  // Stream<bool> get inUpdate => _inUpdateController.stream.asBroadcastStream();
  // StreamSink<bool> get _inUpdateSink => _inUpdateController.sink;

  //需要升级的ota设备
  late BluetoothDevice otaDevice;
  late BluetoothService otaService;
  late File _otaFile;
  List<String> _otaContent = [];
  bool isFirstStep = true;

  bool _otaing = false;

  // late int mtu;

  //一阶段升级用的写入和接收特征码
  BluetoothCharacteristic? appOtaCmdCharacteristic;
  BluetoothCharacteristic? appOtaAskCharacteristic;
  BluetoothCharacteristic? appOtaVersionCharacteristic;
  StreamSubscription<List<int>>? _appOtaAskControl;

  //二阶段升级用的写入和接收特征码
  BluetoothCharacteristic? bootOtaCmdCharacteristic;
  BluetoothCharacteristic? bootOtaAskCharacteristic;
  StreamSubscription<List<int>>? _bootOtaAskControl;

  bool inBackground = false;

  OtaManager._();

  // static OtaManager _instance = OtaManager._();
  static late OtaManager instance;

  bool _isFinded = false;
  bool _isStarted = false;

  bool isOtaDevice(BluetoothDevice device, List<BluetoothService> services) {
    if(_isFinded){
      RunningLogManager.instance.addLog('service is finded');
      return true;
    }
    _isFinded = true;
    for (var service in services) {
      RunningLogManager.instance.addLog('服务id:${service.uuid.toString().toUpperCase()}');
      if(service.uuid.toString().toUpperCase() == APP_OTA_SERVICE_UID
          || service.uuid.toString().toUpperCase() == APP_OTA_SERVICE_UID_V2){
        RunningLogManager.instance.addLog('发现一阶段ota服务');
        if(service.uuid.toString().toUpperCase() == APP_OTA_SERVICE_UID_V2){
          RunningLogManager.instance.addLog('本次升级使用V2版本逻辑');
          isV2Ota = true;
        }
        otaDevice = device;
        isFirstStep = true;
        otaService = service;
        otaService.characteristics.forEach((element) {
          String uuid = element.uuid.toString().toUpperCase();
          if(uuid == APP_OTA_WRITE_UID || uuid == APP_OTA_WRITE_UID_V2){
            appOtaCmdCharacteristic = element;
            if(isV2Ota) {
              bootOtaCmdCharacteristic = element;
            }
          }else if(uuid == APP_OTA_VERSION_UID || uuid == APP_OTA_VERSION_UID_V2){
            appOtaVersionCharacteristic = element;

          }else if(uuid == APP_OTA_NOTIFY || uuid == APP_OTA_NOTIFY_V2){
            appOtaAskCharacteristic = element;
            _listenAppNotify();
          }
        });
        return true;
      }else if(service.uuid.toString().toUpperCase() == BOOT_OTA_SERVICE_UID){
        RunningLogManager.instance.addLog('发现二阶段ota服务');
        otaDevice = device;
        otaService = service;
        isFirstStep = false;

        otaService.characteristics.forEach((element) {
          String uuid = element.uuid.toString().toUpperCase();
          if(uuid == BOOT_OTA_CMD_UID){
            bootOtaCmdCharacteristic = element;
          }else if(uuid == BOOT_OTA_ASK_UID){
            bootOtaAskCharacteristic = element;
            _listenBootNotify();
          }
        });
        return true;
      }
    }
    return false;
  }

  static init(){
    instance = OtaManager._();

  }

  release(){
    Log.d('release ota');
    randMacStr = '';
    _appOtaAskControl?.cancel();
    // appOtaAskCharacteristic?.setNotifyValue(false);

    _bootOtaAskControl?.cancel();
    // bootOtaAskCharacteristic?.setNotifyValue(false);
    bootOtaCmdCharacteristic = null;
    appOtaCmdCharacteristic = null;

    // _timer?.cancel();

    OtaManagerEx.instance.inUpdateSink.add(false);
    OtaManagerEx.instance.progressSink.add(0);
    inProgressing = false;
    // progress = 0;
    _isFinded = false;
    _isStarted = false;
    _otaing = false;
    isV2Ota = false;
    _updateCmdSended = false;
    _curPos = 0;
    instance = OtaManager._();
    if(inBackground){
      return;
    }
    Future.delayed(const Duration(seconds: 1), (){
      BleManager.startScan();
    });
  }



  _listenAppNotify() async {
    Log.d("_listenAppNotify");
    await appOtaAskCharacteristic?.setNotifyValue(true);
    _appOtaAskControl = appOtaAskCharacteristic?.value.listen((event) {
      Log.d('一阶段notify接收到的消息：$event, otaing:$_otaing');
      if(event.isEmpty){
        return;
      }

      if(!_otaing){
        return;
      }

      RunningLogManager.instance.addLog('收到一阶段指令：$event');
      switch(event[0]){
        case 0:
          Log.d('启动升级成功');
          _sendUpdateCmd();
          break;
        case 1:
          _updateErr('写入随机地址不合法');
          break;
        case 2:
          _updateErr('mac code认证失败，目标设备中mac code与APP中用户设置的mac code 不一致');
          break;
        default:
          _updateErr('未知错误码:$event');
      }
    });
  }

  _listenBootNotify() async {
    Log.d("_listenBootNitify");
    await bootOtaAskCharacteristic?.setNotifyValue(true);
    _bootOtaAskControl = bootOtaAskCharacteristic?.value.listen((event) {
      Log.d('二阶段notify接收到的消息：$event, otaing:$_otaing');
      if(event.isEmpty){
        return;
      }

      if(!_otaing){
        return;
      }

      RunningLogManager.instance.addLog('收到二阶段指令：$event');
      switch(event[0]){
        case 1:
          _updateErr('升级过程中收到未知命令');
          break;
        case 2:
          _updateErr('收到不是预期的包类型');
          break;
        case 3:
          _updateErr('收到一个Block之后，计算出的FCS 和 收到的包信息中的FCS不匹配');
          break;
        case 4:
          _updateErr('包信息中收到的Target Adress为非法地址');
          break;
        case 5:
          _updateErr('写入的Credit Code不合法');
          break;
      }
    });
  }

  void _updateErr(String error){
    Fluttertoast.showToast(msg: '升级失败，请通过日志页查看错误原因');
    BleManager.disconnect(otaDevice);
    RunningLogManager.instance.addLog(error);
  }

  void resetOta(){
    BleManager.disconnect(otaDevice);
  }

  BluetoothDeviceState _state = BluetoothDeviceState.disconnected;
  void startOta() {
    if(_isStarted){
      RunningLogManager.instance.addLog("ota is started");
      return;
    }

    _isStarted = true;

    SettingAndFilterManager.instance.writeDataToFile();

    FlutterBlue.instance.state.listen((event) {
      RunningLogManager.instance.addLog('current instance state is : ${event}');
      if(event == BluetoothState.off){
        Fluttertoast.showToast(msg: '蓝牙已关闭，请打开蓝牙后再重启应用').then((value) {
          resetOta();
          release();
          Phoenix.rebirth(Global.navigatorKey.currentState!.context);
        });
      }else if(event == BluetoothState.on){
        BleManager.startScan();
      }
    });

    otaDevice.state.listen((event) {
      if(_state == event){
        return;
      }
      _state = event;
      switch(event){
        case BluetoothDeviceState.disconnected:
          release();
          break;
        case BluetoothDeviceState.connecting:
          // TODO: Handle this case.
          break;
        case BluetoothDeviceState.connected:
          // TODO: Handle this case.
          break;
        case BluetoothDeviceState.disconnecting:
          // TODO: Handle this case.
          break;
      }
    });

    if(inProgressing){
      RunningLogManager.instance.addLog("ota is inProgressing");
      Fluttertoast.showToast(msg: "正在升级中...");
      return;
    }

    _startParseOtaFile();

    // otaDevice.requestMtu(reqMtu).then((value) {
    //   Log.d('申请到的mtu大小为$reqMtu');
    //   mtu = reqMtu;
    //
    //   _startParseOtaFile();
    //
    // }).onError((error, stackTrace) {
    //   Log.d('申请mtu大小$reqMtu报错，错误为$error');
    //   startOta(reqMtu: reqMtu ~/ 2);
    // });
  }

  void _startParseOtaFile() async{
    String filePath = SettingAndFilterManager.instance.filePath;
    RunningLogManager.instance.addLog('OTA文件存储地址：$filePath');
    String newFilePath = await replaceUid(filePath);
    RunningLogManager.instance.addLog('OTA文件IOS私有地址：$newFilePath');
    _otaFile = File(newFilePath);

    if(_otaFile == null){
      Fluttertoast.showToast(msg: "请选择OTA升级文件");
      RunningLogManager.instance.addLog('请选择OTA升级文件');
      BleManager.disconnect(otaDevice);
      return;
    }

    if(!_otaFile.existsSync()){
      Fluttertoast.showToast(msg: "升级文件不存在");
      RunningLogManager.instance.addLog('升级文件不存在');
      BleManager.disconnect(otaDevice);
      return;
    }


    if(!_otaFile.path.endsWith(".hex")){
      Fluttertoast.showToast(msg: "升级文件格式不正确");
      RunningLogManager.instance.addLog('升级文件格式不正确');
      BleManager.disconnect(otaDevice);
      return;
    }

    Log.d('startOta...');
    // inProgressing = true;

    _otaFile.readAsLines().then((value) {
      _otaContent = value;

      String versionInfo =  _otaContent[10];
      // int romInfo = int.parse(versionInfo.substring(0, 4), radix: 16);
      OtaManagerEx.instance.softRom = versionInfo.substring(0, 4);
      // int version = int.parse(versionInfo.substring(4), radix: 16);
      OtaManagerEx.instance.softVersion = versionInfo.substring(4);
      OtaManagerEx.instance.softSize = (_otaFile.lengthSync() ~/ 1024).toString();
      Log.d('文件型号：${OtaManagerEx.instance.softRom}, 版本：${OtaManagerEx.instance.softVersion}, 大小：${OtaManagerEx.instance.softSize} KB');
      // Log.d('文件内容：$_otaContent');
      _compareRomAndVersion();

      // if(isFirstStep){
      //   _startOtaFirstStep();
      // }else{
      //   _startOtaSecondStep();
      // }
    });
  }

  _startOtaInternal(){
    if(isFirstStep){
      _startOtaFirstStep();
    }else{
      _startOtaSecondStep();
    }
  }

  _startOtaFirstStep(){
    Log.d("开始ota第一步");
    RunningLogManager.instance.addLog('发送请求升级指令');
    _createBond();
  }


  //版本校验
  _compareRomAndVersion() async{
    Log.d('delayed 1 seconds...');
    Future.delayed(const Duration(milliseconds: 1500), (){
      if(!isFirstStep){
        _getRomAndVersionFromFile().then((value) {
          OtaManagerEx.instance.chipRom = value.putIfAbsent('chipRom', () => '');
          OtaManagerEx.instance.chipVersion = value.putIfAbsent('chipVersion', () => '');
          _startOtaInternal();
        }).onError((error, stackTrace) {
          RunningLogManager.instance.addLog('读取芯片本地信息失败');
          BleManager.disconnect(otaDevice);
        });
        return;
      }
      //先比较rom
      appOtaVersionCharacteristic?.read().then((value) {
        List<int> bleVersionInfo = convertBytesEndianType(value, 4, EndianType.littleEndian);
        RunningLogManager.instance.addLog("当前版本信息：$bleVersionInfo");
        int _version = _list2Int(bleVersionInfo.sublist(2));
        int _romData = _list2Int(bleVersionInfo.sublist(0, 2));
        OtaManagerEx.instance.chipRom = _list2Str(bleVersionInfo.sublist(0, 2));
        OtaManagerEx.instance.chipVersion = _list2Str(bleVersionInfo.sublist(2));
        _saveRomAndVersion(OtaManagerEx.instance.chipRom, OtaManagerEx.instance.chipVersion);
        Log.d("_compareRomAndVersion then rom is:$_romData, version is:$_version");

        Log.d('romInfo:${OtaManagerEx.instance.softRom}, $_romData');

        bool isRomSame = int.parse(OtaManagerEx.instance.softRom, radix: 16) == _romData;
        RunningLogManager.instance.addLog('ROM校验：蓝牙Rom为$_romData，ota文件Rom为${OtaManagerEx.instance.softRom}, 当前Rom${isRomSame ? '相同, 可以升级' : '不相同, 不能升级'}');

        if(!isRomSame){
          Log.d('Rom不一致，不能升级');
          Fluttertoast.showToast(msg: 'ROM版本不一致');
          BleManager.disconnect(otaDevice);
          return;
        }

        RunningLogManager.instance.addLog('是否需要检测版本号:${SettingAndFilterManager.instance.isVersionCheck ? '需要' : '不需要'}');

        if(SettingAndFilterManager.instance.isVersionCheck){
          int tempVer = int.parse(OtaManagerEx.instance.softVersion, radix: 16);
          Log.d('versionInfo:$tempVer, $_version');
          RunningLogManager.instance.addLog('版本校验：蓝牙版本为$_version, ota文件版本为$tempVer');
          if(_version < tempVer){
            _startOtaInternal();
            return;
          }else{
            Fluttertoast.showToast(msg: '升级版本小于或等于目标设备版本号');
            Log.d('版本一致，不能升级');
            BleManager.disconnect(otaDevice);
            return;
          }
        }
        Log.d('不需要校验版本号');
        _startOtaInternal();
      }).onError((error, stackTrace) {
        BleManager.disconnect(otaDevice);
        Log.e('_compareRomAndVersion onError:$error');
      }).catchError((e){
        BleManager.disconnect(otaDevice);
        Log.e('_compareRomAndVersion catchError : $e');
      });
    });

  }

  //一阶段写入数据方法
  void _writeCmdToAppCharacteristic(List<int> data, {bool withoutResponse = false}){
    if(_state != BluetoothDeviceState.connected){
      return;
    }
    appOtaCmdCharacteristic?.write(data, withoutResponse: withoutResponse).then((value) {
      List<String> dataArr = _list2Hex(data);
      RunningLogManager.instance.addLog('一阶段写入成功:$dataArr');
      if(data == _updateCmd){//升级命令写入成功后，会重启蓝牙，所以这个时候应该断开蓝牙并重新搜索
        if(isV2Ota){
          RunningLogManager.instance.addLog('直接开始二阶段逻辑');
          _startOtaSecondStep();
        }else {
          RunningLogManager.instance.addLog('老版本逻辑，先断开重新扫描，待连接后再执行升级');
          BleManager.disconnect(otaDevice);
        }
        // Future.delayed(const Duration(seconds: 1), (){
        //   BleManager.startScan();
        // });
      }
    }).onError((error, stackTrace) {
      BleManager.disconnect(otaDevice);
      Log.d('一阶段写入报错:$error');
      RunningLogManager.instance.addLog('一阶段写入报错：$error');
    }).catchError((onError){
      BleManager.disconnect(otaDevice);
      Log.d('一阶段写入异常:$onError');
      RunningLogManager.instance.addLog('一阶段写入异常：$onError');
    }).timeout(const Duration(seconds: 1), onTimeout: (){
      RunningLogManager.instance.addLog('一阶段写入超时');
      BleManager.disconnect(otaDevice);
    });
  }

  Timer? bondTimer;
  //发起配对
  _createBond(){
    Log.d('不需要配对，直接发送命令');
    _sendCharacteristicCode();
    // if(!SettingAndFilterManager.instance.isBondCheck){
    //   Log.d('不需要配对，直接发送命令');
    //   _sendCharacteristicCode();
    //   return;
    // }
    // BleManager.createBond(otaDevice);
    // RunningLogManager.instance.addLog('开始配对');
    // bondTimer = Timer.periodic(const Duration(seconds: 1), (_) {
    //   otaDevice.bondState.then((value) {
    //     Log.d('bondState:$value');
    //     if(value == BluetoothBondState.bonded){
    //       RunningLogManager.instance.addLog('配对成功');
    //       bondTimer?.cancel();
    //       _sendCharacteristicCode();
    //     }else if(value == BluetoothBondState.bonding){
    //       RunningLogManager.instance.addLog('配对中');
    //     }else{
    //       RunningLogManager.instance.addLog('配对失败');
    //     }
    //   }).timeout(const Duration(seconds: 10), onTimeout: (){
    //     Log.d('bond timeout...');
    //     RunningLogManager.instance.addLog('配对超时');
    //     bondTimer?.cancel();
    //     _sendCharacteristicCode();
    //   });
    // });
  }

  //一阶段发送特征码
  String randMacStr = '';
  _sendCharacteristicCode(){
    List<int> randMac;
    if(Platform.isIOS){
      randMac = [
        0xc2,
        0x6d,
        0x69,
        0xc4,
        0xc7,
        0xe7
      ];
    }else {
      randMac = convertBytesEndianType(_generateMacAddress(), 6, EndianType.littleEndian);
    }
    List<int> creditCode = convertBytesEndianType(_string2List(SettingAndFilterManager.instance.creditCode), 4, EndianType.littleEndian);
    List<int> macCode = _string2List(SettingAndFilterManager.instance.macCode);

    _writeCmdToAppCharacteristic([...creditCode, ...randMac, ...macCode]);

    randMacStr = convertBytesEndianType(randMac, 6, EndianType.littleEndian).map((e){
      String hex = e.toRadixString(16);
      if(hex.length == 1){
        hex = "0$hex";
      }
      return hex;
    }).join(':').toUpperCase();
    Log.d('随机地址为：$randMacStr');
    _otaing = true;
    // Future.delayed(const Duration(milliseconds: 80), (){
    //   _sendUpdateCmd();
    // });
  }

  bool _updateCmdSended = false;
  //一阶段发送升级命令
  List<int> _updateCmd = [0x63, 0x69, 0x6d, 0x72];
  _sendUpdateCmd(){
    if(_updateCmdSended){
      return;
    }
    RunningLogManager.instance.addLog('发送升级指令');
    List<int> updateCmd = _updateCmd;
    _writeCmdToAppCharacteristic(updateCmd);
    _updateCmdSended = true;
  }


  List<int> _string2List(String data){
    // int num = int.parse(data);
    // ByteData bd = ByteData(4);
    // bd.setInt32(0, num);
    List<int> bytes = HEX.decode(data);
    // Log.d(bytes); // [0, 1, 255, 255]
    return bytes;
  }

  String _list2Str(List<int> bytes){
    String result = '';
    for (var value in bytes) {
      String hex = value.toRadixString(16);
      if(hex.length == 1){
        hex = '0$hex';
      }
      result = result + hex;
    }
    return result;
  }

  int _list2Int(List<int> bytes) {
    String result = _list2Str(bytes);
    // for (var value in bytes) {
    //   String hex = value.toRadixString(16);
    //   if(hex.length == 1){
    //     hex = '0$hex';
    //   }
    //   result = result + hex;
    // }
    return int.parse(result, radix: 16);
  }

  //生成随机地址
  List<int> _generateMacAddress() {
    var random = Random();
    var mac = List.generate(6, (_) => random.nextInt(256));
    return mac;//.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(':');
  }

  // Timer? _timer;

  _startOtaSecondStep(){
    inProgressing = true;
    OtaManagerEx.instance.inUpdateSink.add(true);
    _curPos = 0;
    RunningLogManager.instance.addLog('开始ota第二步');
    Future.delayed(const Duration(milliseconds: 100), (){
      _delayedRecursiveCall();
    });
  }

  int _curPos = 0;
  static const int DATA_SIZE = 32;

  _sendOtaStart(){

    List<int> creditCode = convertBytesEndianType(_string2List(SettingAndFilterManager.instance.creditCode), 4, EndianType.littleEndian);
    List<int> cmd = [01,01,...creditCode];
    _writeCmdToBootCharacteristic(cmd);
    _curPos = 3;
    _otaing = true;
  }

  _sendBlockCmd(){
    String blockStr = _otaContent[_curPos];
    // Log.d('_sendBlockCmd blockStr ${blockStr.substring(1)}');
    List<int> targetAddr = convertBytesEndianType(_string2List(blockStr.substring(1, 9)), 4, EndianType.littleEndian);
    int start = _curPos + 1;
    int end = start + 1024;
    if(end > _otaContent.length){
      end = _otaContent.length;
    }

    List<int> targeSize = encodeEndian((end - start) * 4, 2, endianType: EndianType.littleEndian);

    List<String> blockDataStr = _otaContent.sublist(start, end);
    List<int> blockDataArr = [];
    for(String data in blockDataStr){
      blockDataArr.addAll(convertBytesEndianType(_string2List(data), 4, EndianType.littleEndian));
    }
    List<int> blockFcs = convertBytesEndianType(FCSUtil.calculateFCS(blockDataArr), 3, EndianType.littleEndian);

    // Log.d("_sendBlockCmd targetAddr:$targetAddr, targetSize:$targeSize, blockFcs:$blockFcs");
    List<int> cmd = [01,04, ...targetAddr, ...targeSize, ...blockFcs];
    // Log.d("_sendBlockCmd targetAddr cmd:$cmd");
    _writeCmdToBootCharacteristic(cmd);
    _curPos += 1;
  }

  _sendBlockData(){
    List<String> segData = [];
    int size = DATA_SIZE;
    if(_curPos + DATA_SIZE > _otaContent.length){
      size = _otaContent.length - _curPos;
    }
    segData = _otaContent.sublist(_curPos, _curPos + size);
    List<int> cmd = [];
    for(String data in segData){
      cmd.addAll(convertBytesEndianType(_string2List(data), 4, EndianType.littleEndian));
    }
    _writeCmdToBootCharacteristic(cmd);
    _curPos += size;
    // Log.d('_sendBlockData size is : $size');
  }

  final List<int> _endCmd = [01, 03];
  _sendEndOta(){
    Future.delayed(const Duration(milliseconds: 200), () {
      Log.d('_sendEndOta...');
      _writeCmdToBootCharacteristic(_endCmd, withoutResponse: false);
      HistoryManager.instance.saveHistory(HistoryInfo.fromOta(otaDevice.name, otaDevice.id.id, 'Success', 'all data loaded'));
    });
  }

  //二阶段写入数据方法
  void _writeCmdToBootCharacteristic(List<int> data, {bool withoutResponse = false}){
    if(_state != BluetoothDeviceState.connected){
      return;
    }
    bootOtaCmdCharacteristic?.write(data, withoutResponse: withoutResponse).then((value) {
      int progress = _curPos * 100 ~/ (_otaContent.length - 1);
      OtaManagerEx.instance.progressSink.add(progress);

      List<String> dataArr = _list2Hex(data);
      // Log.d('二阶段写入成功:$dataArr');
      RunningLogManager.instance.addLog('写入指令(数据)：$dataArr');
      if(data == _endCmd){
        RunningLogManager.instance.addLog('所有数据写入完成');
      }else{
        _delayedRecursiveCall();
      }
    }).onError((error, stackTrace) {
      // Log.d('二阶段写入报错:$error');
      // Log.d('二阶段写入报错:$stackTrace');
      RunningLogManager.instance.addLog('二阶段写入报错：$error');
      BleManager.disconnect(otaDevice);
    }).catchError((onError){
      // Log.d('二阶段写入异常:$onError');
      RunningLogManager.instance.addLog('二阶段写入异常：$onError');
      BleManager.disconnect(otaDevice);
    }).timeout(const Duration(seconds: 1), onTimeout: (){
      RunningLogManager.instance.addLog('二阶段写入超时');
      BleManager.disconnect(otaDevice);
    });
  }

  Future<void> _delayedRecursiveCall() async {
    if(_curPos == 0){
      RunningLogManager.instance.addLog('sendOtaStart...');
      _sendOtaStart();
    }else {
      String blockStr = _otaContent[_curPos];
      Log.d('_startOtaSecondStep curStr $blockStr, curPos:$_curPos');
      if (_curPos >= _otaContent.length - 1) {
        _sendEndOta();
      } else if (blockStr.startsWith('@')) {
        _sendBlockCmd();
      } else {
        _sendBlockData();
      }
    }

  }

  List<String> _list2Hex(List<int> bytes) {
    List<String> result = [];
    for (var value in bytes) {
      result.add(value.toRadixString(16));
    }
    return result;
  }


  void _saveRomAndVersion(String rom, String version) {

    if(Platform.isAndroid){
      getExternalStorageDirectory().then((value) {
        _saveRomAndVersionInternal(value!, rom, version);
      });
    }else if(Platform.isIOS){
      getApplicationDocumentsDirectory().then((value) {
        _saveRomAndVersionInternal(value, rom, version);
      });
    }else{
      throw UnsupportedError('not support platform ${Platform.localeName}');
    }
  }


  void _saveRomAndVersionInternal(Directory value, String rom, String version){
    Map<String, dynamic> map = {};
    map['chipRom'] = rom;
    map['chipVersion'] = version;

    _savePath('${value.path}/chip_info', convert.jsonEncode(map));
  }

  void _savePath(String path, String data){
    Log.d('chip info path:$path');
    File file = File(path);
    if(!file.existsSync()) {
      file.createSync(recursive: true);
    }

    file.writeAsString(data, flush: true);
    if(file.existsSync()) {
      Log.d('数据：$data保存成功');
    }
  }

  //读取指定文件中的数据
  Future<Map> _getRomAndVersionFromFile() async {
    Directory? documentsDir;//await getApplicationDocumentsDirectory();
    if(Platform.isAndroid){
      documentsDir = await getExternalStorageDirectory();
    }else if(Platform.isIOS){
      documentsDir = await getApplicationDocumentsDirectory();
    }else{
      throw UnsupportedError('not support platform ${Platform.localeName}');
    }
    String? documentsPath = documentsDir?.path;

    File file = File('$documentsPath/chip_info');
    if(!file.existsSync()) {
      return {};
    }

    String filterTxt = await file.readAsString();
    Map<String, dynamic> map = convert.jsonDecode(filterTxt);
    return map;

  }
}